/**
 * Copyright (c) 2011 Basil Shikin, VintageRadio Project
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.vintagephone.model.player;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.vintagephone.model.MusicFolder;
import org.vintagephone.model.Song;
import org.vintagephone.model.player.Player.NextSongCallback;

import android.content.Context;
import android.media.AudioManager;
import android.util.Log;

/**
 * This class is used to track available songs and feed properly feed next
 * song to the player
 * @author Basil Shikin
 *
 */
public class PlayerControl 
{
	protected static final String Tag = "PlayerControl";

	// Parent objects
	private final Context m_context;
	
	// Controlled objects
	private final Object m_songControlLock = new Object();
	private final PlayerMediaScanner m_scanner;
	private final Player m_player;
	
	// State variables
	private MusicFolder m_activeFolder;
	private Song m_activeSong;
	
	private final Map<MusicFolder, Song> m_activeSongs = new HashMap<MusicFolder, Song>();
	private final Map<MusicFolder, List<Song>> m_folderSongs = new HashMap<MusicFolder, List<Song>>();

    

	public PlayerControl( Context context )
	{
	    m_context = context;
	    
		m_scanner = new PlayerMediaScanner( context );
		m_player = new Player();
	}
	
	public void initialize()
	{
	}
	
	public void setNextSongCallback( final NextSongCallback nextSongCallback )
	{
	    m_player.setNextSongCallback( nextSongCallback );
	}
	
	public Song switchToFolder( MusicFolder folder )
	{
        // Determine what song to play now
        final Song activeSong;

		synchronized ( m_songControlLock ) 
		{
			m_activeFolder  = folder;
			
			final List<Song> folderSongs = PlayerUtils.loadFolderSongs( folder );
			
			if ( !folderSongs.isEmpty() )
			{
			    // Shuffle songs
			    if ( folder != MusicFolder.FOUR )
			    {
			        Collections.shuffle( folderSongs );
			    }
			    
				// Schedule a scan of folder songs
				scanFolderSongs( folderSongs );
				
				if ( m_activeSongs.get( folder ) != null )
				{
					final Song possibleSong = m_activeSongs.get( folder );
					if ( folderSongs.contains( possibleSong ) )
					{
						activeSong = possibleSong;
					}
					else if ( !folderSongs.isEmpty() )
					{
						activeSong = folderSongs.get( 0 );
					}
					else
					{
						activeSong = null;
					}
				}
				else if ( !folderSongs.isEmpty() )
				{
					activeSong = folderSongs.get( 0 );
				}
				else
				{
					activeSong = null;
				}
				
				if ( activeSong != null )
				{
					m_activeSong = activeSong;
					
					playSong( activeSong );
				}
				
				m_activeSongs.put( folder, activeSong );
			}
			else
			{
			    activeSong = null;
			}
			
			// Save songs in active folder
			m_folderSongs.put( folder, folderSongs );
		}
		
		return activeSong;
	}
	
	public Song switchToNextSong()
	{
		synchronized ( m_songControlLock ) 
		{
			if ( m_activeSong != null )
			{
				final List<Song> activeFolderSongs = m_folderSongs.get( m_activeFolder );
				
				final int currentSongIx = activeFolderSongs.indexOf( m_activeSong );
				final int nextSongIx = (currentSongIx + 1) % activeFolderSongs.size();
				
				final Song activeSong = activeFolderSongs.get( nextSongIx );
				playSong(activeSong);
			}
			
			return m_activeSong;
		}
	}
	
	public Song switchToPreviousSong()
	{
		synchronized ( m_songControlLock ) 
		{
			if ( m_activeSong != null )
			{
				final List<Song> activeFolderSongs = m_folderSongs.get( m_activeFolder );
				
				final int currentSongIx = activeFolderSongs.indexOf( m_activeSong );
				final int nextSongIx = currentSongIx > 0 ? currentSongIx - 1 : activeFolderSongs.size() - 1; 
				
				final Song activeSong = activeFolderSongs.get( nextSongIx );
				playSong(activeSong);
			}
			
			return m_activeSong;
		}
	}
	
	public Song setIsOn(boolean isOn)
    {
	    if ( isOn )
	    {
	        Log.d(Tag, "Resuming platback...");
            
            if ( m_activeSong != null )
            {
                m_player.play( m_activeSong );
            }
            else
            {
                switchToNextSong();
            }
            
            return m_activeSong;
	    }
	    else
	    {
	        Log.d(Tag, "Pausing platback...");
            
            m_player.pause();
            
            return null;
	    }
    }
	
	public void setVolume(int percent)
    {
	    final AudioManager audioManager = (AudioManager)m_context.getSystemService(Context.AUDIO_SERVICE);
	    
	    final int streamType = AudioManager.STREAM_MUSIC;
	    final int maxVolume = audioManager.getStreamMaxVolume( streamType );
	    
	    final int newVolume = Math.round( (percent/100F)*maxVolume );
	    audioManager.setStreamVolume(streamType, newVolume, 0 );
    }
	
	public List<Song> getActiveFolderSongs()
	{
		synchronized ( m_songControlLock ) 
		{
			return m_folderSongs.get( m_activeFolder );
		}
	}
	
	private void scanFolderSongs(List<Song> folderSongs) 
	{
		for ( Song song : folderSongs )
		{
			m_scanner.scanSong( song );
		}
	}

	private void playSong(Song activeSong) 
	{
		Log.d(Tag, "Playing: " + activeSong );
		
		if ( activeSong != null )
		{
			m_activeSong = activeSong;
			m_activeSongs.put( m_activeFolder, activeSong);
			
			m_player.play( activeSong );
		}
		else
		{
			m_player.stop();
		}
	}
}
